package lib.rv.ap

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView

interface IDiffVhModelType : IViewTypeModel {
    /**
     * 默认同一个对象内容不一样。
     */
    fun areContentsTheSame(other: IDiffVhModelType): Boolean {
        return false
    }

    /**
     * 默认同一个对象就是同一个item。
     */
    fun areItemsTheSame(other: IDiffVhModelType): Boolean {
        return this == other
    }
}
abstract class CBaseDiffListAdapter(diffCallback: DiffCallBack = DiffCallBack())
    : ListAdapter<IDiffVhModelType, CBaseDiffListAdapter.BindingViewHolder>(diffCallback) {

    class BindingViewHolder(val binding: ViewDataBinding) : RecyclerView.ViewHolder(binding.root)

    private val ivdManager: ViewTypeDelegateManager<IDiffVhModelType> =
            ViewTypeDelegateManager()

    // 只读的list。
    private val readOnlyList: MutableList<IDiffVhModelType> = ArrayList()

    // 上一次list。
    private var lastList: List<IDiffVhModelType>? = null

    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        addDelegate(ivdManager)
        super.onAttachedToRecyclerView(recyclerView)
    }

    override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
        ivdManager.clear()
        super.onDetachedFromRecyclerView(recyclerView)
    }

    abstract fun onCreateVHForAll(binding: ViewDataBinding)

    abstract fun onBindVHForAll(binding: ViewDataBinding, m: IDiffVhModelType)

    /**
     * 初始化各种viewType处理委托。添加到Manager中。
     */
    protected open fun addDelegate(manager: ViewTypeDelegateManager<IDiffVhModelType>) {
    }

    override fun getItemViewType(position: Int): Int {
        return getItem(position)?.getViewType() ?: 0
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingViewHolder {
        val holder = createVH(parent, viewType)
        onCreateVHForAll(holder.binding)
        ivdManager.onCreateVH(holder.binding, viewType)
        return holder
    }

    protected open fun createVH(parent: ViewGroup, viewType: Int): BindingViewHolder {
        val binding = DataBindingUtil.inflate<ViewDataBinding>(
                LayoutInflater.from(parent.context), viewType, parent, false)
        return BindingViewHolder(binding)
    }

    override fun onBindViewHolder(holder: BindingViewHolder, position: Int) {
        onBindVHForAll(holder.binding, getItem(position))
        ivdManager.onBindVH(holder.binding, getItem(position))
        holder.binding.executePendingBindings()
    }

    /**
     * 数据刷新方法。
     */
    @Suppress("UselessCallOnCollection")
    override fun submitList(list: List<IDiffVhModelType>?) {
        lastList = (modify?.modify(list) ?: list?.toList())?.filterNotNull()
        super.submitList(lastList)
        readOnlyList.clear()
        readOnlyList.addAll(lastList ?: return)
    }

    /**
     * 只读的List。对它修改不会影响到真实的列表。
     * 它的数据不一定与真实数据一致。由于DiffUtils是异步操作，真实数据的更新会慢于只读的list。
     *
     * @since 3.0.0
     */
    fun getReadOnlyList(): List<IDiffVhModelType> {
        return readOnlyList
    }

    /**
     * 刷新指定的Item。
     *
     * PS：请不要与submitList 连着使用。
     *
     * @since 3.0.0
     */
    fun changeItems(itemList: List<IDiffVhModelType>?) {
        val multiList = (modify?.modify(itemList) ?: itemList) ?: return
        for (m in multiList) {
            if (m in readOnlyList) {
                val position = readOnlyList.indexOf(m)
                if (position in 0 until itemCount) {
                    notifyItemChanged(position)
                }
            }
        }
    }

    private var modify: IModify? = null

    /**
     * 设置列表变换。
     */
    fun setModify(modify: IModify?) {
        this.modify = modify
    }

    // 变换规则接口，可自定义。
    interface IModify {
        /**
         * List数据结构需要改变时重写。即传入 List 经过变化后变成 items 需要的list。默认不改变结构。
         */
        fun modify(list: List<IDiffVhModelType>?): List<IDiffVhModelType>?
    }

    open class DiffCallBack : DiffUtil.ItemCallback<IDiffVhModelType>() {
        // 判断两个item内容是否相同。
        override fun areContentsTheSame(oldItem: IDiffVhModelType, newItem: IDiffVhModelType): Boolean {
            return oldItem.areContentsTheSame(newItem)
        }

        // 判断两个item是否用同哟个item。
        override fun areItemsTheSame(oldItem: IDiffVhModelType, newItem: IDiffVhModelType): Boolean {
            return oldItem.areItemsTheSame(newItem)
        }

        // 高级用法，用来提取变化量，做局部变量精准刷新。暂时不用。
        override fun getChangePayload(oldItem: IDiffVhModelType, newItem: IDiffVhModelType): Any? {
            return null
        }
    }
}